package tech.aistar.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import tech.aistar.constants.JwtClaimsConstant;
import tech.aistar.constants.MessageConstant;
import tech.aistar.constants.RedisConstant;
import tech.aistar.mapper.UserInfoMapper;
import tech.aistar.mapper.UserMapper;
import tech.aistar.pojo.User;
import tech.aistar.pojo.UserInfo;
import tech.aistar.pojo.dto.UserRegisterDTO;
import tech.aistar.pojo.result.ResultReturn;
import tech.aistar.service.UserService;
import tech.aistar.utils.JwtUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AsyncService asyncService;
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Override
    public ResultReturn loginByName(User user) {
        User userByDB = userMapper.selectByUserName(user.getUsername());
        if (userByDB == null) {
            return ResultReturn.fail(MessageConstant.USER_NOT_EXITS);
        }
        //比较密码
        String pwdMD5 = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        if (!pwdMD5.equals(userByDB.getPassword())) {
            //密码错误
            return ResultReturn.fail(MessageConstant.PWD_ERR);
        }
        //TODO 生成jwt令牌
        String token = JwtUtils.generateToken(userByDB);
        //TODO ysx 返回token和username
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("username",userByDB.getUsername());
        return ResultReturn.success(map);
    }

    @Override
    public ResultReturn sendCodeRegisterPhone(String phone) {
        User user = userMapper.selectByPhone(phone);
        if (user != null) {
            return ResultReturn.fail(MessageConstant.USER_HAVE_REGISTER);
        }
        String code = RandomUtil.randomNumbers(6);
        log.info("{}-code:{}", phone,code);
        stringRedisTemplate.opsForValue().set(
                RedisConstant.REGISTER_PHONE_CODE + phone,
                code,
                3,
                TimeUnit.MINUTES
                );
        return ResultReturn.success();
    }

    @Override
    public ResultReturn sendCodeRegisterEmail(String email) {
        User user = userMapper.selectByEmail(email);
        if (user != null) {
            return ResultReturn.fail(MessageConstant.USER_HAVE_REGISTER);
        }
        asyncService.sendMailCode(email,RedisConstant.REGISTER_EMAIL_CODE);
        return ResultReturn.success();
    }

    @Transactional
    @Override
    public ResultReturn register(UserRegisterDTO userRegisterDTO) {
        User user = userMapper.selectByUserName(userRegisterDTO.getUsername());
        //用户名被占用
        if (user != null) {
            return ResultReturn.fail(MessageConstant.USERNAME_HAVE_EXITS);
        }
        String phone = userRegisterDTO.getPhone();
        String email = userRegisterDTO.getEmail();
        String code = null;
        //获取redis存的验证码
        if (phone == null && email != null) {
           code = stringRedisTemplate.opsForValue().get(RedisConstant.REGISTER_EMAIL_CODE + email);
        }else{
            if (phone != null && email == null) {
                code = stringRedisTemplate.opsForValue().get(RedisConstant.REGISTER_PHONE_CODE + phone);
            }else{
                return ResultReturn.fail(MessageConstant.PARAM_ERR);
            }
        }
        //比较验证码
        if(code == null){
            return ResultReturn.fail(MessageConstant.CODE_TIMEOUT);
        }
        if (!userRegisterDTO.getCode().equals(code)) {
            return ResultReturn.fail(MessageConstant.CODE_ERR);
        }
        //加密密码
        String pwd =  DigestUtils.md5DigestAsHex(userRegisterDTO.getPassword().getBytes());
        userRegisterDTO.setPassword(pwd);
        User insertUser = new User();
        BeanUtils.copyProperties(userRegisterDTO,insertUser);
        int result = userMapper.insert(insertUser);
        if (result > 0) {
            UserInfo userInfo = new UserInfo();
            userInfo.setUserId(insertUser.getUserId());
            userInfoMapper.add(userInfo);
            return ResultReturn.success();
        }else{
            return ResultReturn.fail(MessageConstant.FAIL);
        }
    }

    @Override
    public ResultReturn loginByCode(UserRegisterDTO userRegisterDTO) {
        String phone = userRegisterDTO.getPhone();
        String email = userRegisterDTO.getEmail();
        String code = null;
        User user = null;
        //获取redis存的验证码
        if (phone == null && email != null) {
            user = userMapper.selectByEmail(email);
            if (user == null) {
                return ResultReturn.fail(MessageConstant.USER_NOT_EXITS);
            }
            code = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_EMAIL_CODE + email);
        }else{
            if (phone != null && email == null) {
                user = userMapper.selectByPhone(phone);
                if (user == null) {
                    return ResultReturn.fail(MessageConstant.USER_NOT_EXITS);
                }
                code = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_PHONE_CODE + phone);
            }else{
                return ResultReturn.fail(MessageConstant.PARAM_ERR);
            }
        }
        //比较验证码
        if(code == null){
            return ResultReturn.fail(MessageConstant.CODE_TIMEOUT);
        }
        if (!userRegisterDTO.getCode().equals(code)) {
            return ResultReturn.fail(MessageConstant.CODE_ERR);
        }
        //TODO 生成jwt令牌
        String token = JwtUtils.generateToken(user);
        //TODO ysx 返回token和username
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("username",user.getUsername());
        return ResultReturn.success(map);
    }

    /**
     * 手机发送登录验证码
     * @param phone
     * @return
     */
    @Override
    public ResultReturn sendCodeLoginPhone(String phone) {
        User user = userMapper.selectByPhone(phone);
        if (user == null) {
            return ResultReturn.fail(MessageConstant.USER_NOT_EXITS);
        }
        String code = RandomUtil.randomNumbers(6);
        log.info("{}-code:{}", phone,code);
        stringRedisTemplate.opsForValue().set(
                RedisConstant.LOGIN_PHONE_CODE + phone,
                code,
                3,
                TimeUnit.MINUTES
        );
        return ResultReturn.success();
    }

    /**
     * 邮箱发送登录验证码
     * @param email
     * @return
     */
    @Override
    public ResultReturn sendCodeLoginEmail(String email) {
        User user = userMapper.selectByEmail(email);
        if (user == null) {
            return ResultReturn.fail(MessageConstant.USER_NOT_EXITS);
        }
        asyncService.sendMailCode(email,RedisConstant.LOGIN_EMAIL_CODE);
        return ResultReturn.success();
    }
}
